#ifndef PROTOCOL_BUFF_H
#define PROTOCOL_BUFF_H
#include <string.h>

#define PROTO_HEAD_LEN (5)

#define CreateRecvBuff(sz) \
    static unsigned char __protoBuff[sz] = {0}; \
    static unsigned int  __protoBuffLen  = sz;  \
    static unsigned int  __protoBuffRPos = 0;   \
    static unsigned int  __protoBuffWPos = 0;   \
    static unsigned char __protoDataCahce[sz] = {0};   \
    static unsigned int  __protoDataLen  = 0;\
    static unsigned char __protoDataType = 0;

#define PushRecvBuff(p,len) do{\
    for( int i=0; i<len; ++i ){\
        ++__protoBuffWPos;\
        if( __protoBuffWPos > __protoBuffLen-1 ){ __protoBuffWPos = 0; }\
        __protoBuff[__protoBuffWPos] = p[i];\
    }\
}while(0)


#define SkipRecvBuff(n) do{\
    if(n>0){\
        unsigned int CurLen1 = 0, CurLen2 = 0;\
        if( __protoBuffRPos < __protoBuffWPos ){\
            CurLen1 = __protoBuffWPos-__protoBuffRPos;\
        }else if( __protoBuffRPos > __protoBuffWPos ){\
            CurLen1 = __protoBuffLen-__protoBuffRPos-1;\
            CurLen2 = __protoBuffWPos;\
        }\
        unsigned int CurLen = CurLen1+CurLen2;\
        if( CurLen ){\
            if( n>=CurLen ){\
                __protoBuffRPos = __protoBuffWPos;\
            }else{\
                if( n<=CurLen1 ){ __protoBuffRPos+=n; }\
                else{\
                    __protoBuffRPos = n-CurLen1-1;\
                }\
            }\
        }\
    }\
}while(0)

//void Recv_Callback(unsigned char type, unsigned char*pdata, int len ){}
#define AnalyzeRecvBuff(cb) do{\
    unsigned int bBreak = 1;\
    unsigned int CurLen1 = 0;\
    unsigned int CurLen2 = 0;\
    if( __protoBuffRPos < __protoBuffWPos ){\
        CurLen1 = __protoBuffWPos-__protoBuffRPos;\
    }else if( __protoBuffRPos > __protoBuffWPos ){\
        CurLen1 = __protoBuffLen-__protoBuffRPos-1;\
        CurLen2 = __protoBuffWPos;\
    }\
    unsigned int CurLen = CurLen1+CurLen2;\
    if( CurLen ){\
        unsigned char* temp = __protoDataCahce;\
        if( __protoDataLen && CurLen>=__protoDataLen ){\
            if(CurLen1){ memcpy(temp,__protoBuff+__protoBuffRPos+1,CurLen1); }\
            if(CurLen2){ memcpy(temp+CurLen1,__protoBuff,CurLen2); }\
            cb(__protoDataType,temp,__protoDataLen);\
            SkipRecvBuff(__protoDataLen);\
            __protoDataLen = 0;\
            bBreak = !(CurLen>__protoDataLen);\
        }else if( __protoDataLen==0 && CurLen>=PROTO_HEAD_LEN ){\
            if(CurLen1){ memcpy(temp,__protoBuff+__protoBuffRPos+1,CurLen1); }\
            if(CurLen2){ memcpy(temp+CurLen1,__protoBuff,CurLen2); }\
            int nHeadPos = -1;\
            for( int i=0; i<CurLen-1; ++i ){\
                if( 0x55 == temp[i] && 0x55 == temp[i+1] ){ nHeadPos = i; break; }\
            }\
            if( nHeadPos>-1 ){\
                int ValidLen = CurLen-nHeadPos;\
                if( ValidLen>=PROTO_HEAD_LEN ){\
                    __protoDataType = *(temp+nHeadPos+2);\
                    unsigned int HLen = *(temp+nHeadPos+3);\
                    unsigned int LLen = *(temp+nHeadPos+4);\
                    __protoDataLen = HLen<<8|LLen;\
                    if( __protoDataLen<=__protoBuffLen ){\
                        SkipRecvBuff( nHeadPos+PROTO_HEAD_LEN );\
                        bBreak = !(ValidLen>PROTO_HEAD_LEN);\
                    }else{ __protoBuffRPos = __protoBuffWPos; __protoDataLen=0; }\
                }else{\
                    SkipRecvBuff(nHeadPos);\
                }\
            }\
        }\
    }\
    if( bBreak ){ break; }\
}while(1)

//void func_send(unsigned char*pdata, int len ){}
#define SendProtoBuff(type,p,len,func_send) do{\
    if( len<=0xFFFF ){\
        unsigned char pHead[PROTO_HEAD_LEN] = {0x55,0x55,type,(len>>8)&0xFF,(len)&0xFF};\
        func_send(pHead,PROTO_HEAD_LEN);\
        func_send(p,len);\
    }\
}while(0)

#endif
